package com.supermarket.api.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.supermarket.api.bean.user.LoginReq;
import com.supermarket.api.bean.user.LoginRes;
import com.supermarket.api.bean.user.RegisterReq;
import com.supermarket.api.bean.user.TokenData;
import com.supermarket.api.common.Constants;
import com.supermarket.api.common.ErrorMessage;
import com.supermarket.api.common.exception.BaseException;
import com.supermarket.api.common.filters.UserCacheManage;
import com.supermarket.api.common.redis.RedisConstants;
import com.supermarket.api.common.redis.RedisOperate;
import com.supermarket.api.common.utils.EncryptionUtil;
import com.supermarket.api.common.utils.ValidatorUtil;
import com.supermarket.api.entity.UserInfoEntity;
import com.supermarket.api.enums.SexType;
import com.supermarket.api.enums.UserStatusType;
import com.supermarket.api.repository.UserInfoRepository;
import com.supermarket.api.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.Optional;
import java.util.UUID;

/**
 * 用户服务层
 * @author 李其伟
 * @date 2023/10/29
 */
@Slf4j
@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private RedisOperate redisOperate;

    @Autowired
    private UserInfoRepository userRepository;

    /**
     * accessTime的过期时间
     */
    @Value("${apiserver.token.accessTime}")
    private int accessTime;
    /**
     * refreshTime的过期时间
     */
    @Value("${apiserver.token.refreshTime}")
    private int refreshTime;

    /**
     * 新建用户默认头像
     */
    @Value("${apiserver.user.avatar}")
    private String defaultAvatar;

    @Override
    public boolean register(RegisterReq registerReq) {
        //验证是否重复
        UserInfoEntity userInfoEntity = userRepository.findAllByPhone(registerReq.getPhone());
        Assert.isNull(userInfoEntity,"手机号已经存在");
        userInfoEntity = userRepository.findAllByEmail(registerReq.getEmail());
        Assert.isNull(userInfoEntity,"邮箱已经存在");
        userInfoEntity = userRepository.findAllByLoginName(registerReq.getLoginName());
        Assert.isNull(userInfoEntity,"登陆名已经存在");

        UserInfoEntity entity = new UserInfoEntity();
        BeanUtils.copyProperties(registerReq,entity);
        entity.setPassword(EncryptionUtil.SHA(entity.getPassword()));
        entity.setCreateTime(new Date());
        entity.setAvatar(defaultAvatar);
        entity.setEmailVerify(false);
        entity.setPhoneVerify(false);
        entity.setSex(SexType.UNKNOWN.getSex());
        entity.setLevel(Constants.DEFAULT_USER_LEVEL);
        entity.setStatus(UserStatusType.AUDIT.getStatus());
        userRepository.save(entity);

        return true;
    }

    @Override
    public LoginRes login(LoginReq loginReq) {
        //查询信息
        String loginName = loginReq.getLoginName();
        UserInfoEntity userInfoEntity ;
        if(ValidatorUtil.isMobile(loginName)){
            userInfoEntity = userRepository.findAllByPhone(loginName);
        }else if(ValidatorUtil.isEmail(loginName)){
            userInfoEntity = userRepository.findAllByEmail(loginName);
        }else {
            userInfoEntity = userRepository.findAllByLoginName(loginName);
        }
        Assert.notNull(userInfoEntity,"登陆名或密码错误");

        //验证密码
        String pass = EncryptionUtil.SHA(loginReq.getPassword());
        Assert.isTrue(userInfoEntity.getPassword().equals(pass),"登陆名或密码错误");

        LoginRes loginRes = new LoginRes();
        BeanUtils.copyProperties(userInfoEntity,loginRes);

        //设置缓存
        String accessUuid = UUID.randomUUID().toString().replace("-","");
        String refreshUuid = UUID.randomUUID().toString().replace("-","R");
        String data = JSONObject.toJSONString(loginRes);

        redisOperate.set(RedisConstants.ACCESS_TOKE+accessUuid, data ,accessTime);
        redisOperate.set(RedisConstants.REFUSE_TOKEN+refreshUuid, data ,refreshTime);

        loginRes.setAccessToken(accessUuid);
        loginRes.setRefreshToken(refreshUuid);
        return loginRes;
    }

    @Override
    public TokenData refresh(TokenData tokenData) {
        String key = RedisConstants.REFUSE_TOKEN+tokenData.getRefreshToken();
        String value = redisOperate.get(key);
        //Redis查询token不存在
        if(StringUtils.isEmpty(value)){
            throw new BaseException(ErrorMessage.ERR_REFUSE_TOKEN_FAIL);
        }
        //删除之前缓存
        redisOperate.delete(RedisConstants.REFUSE_TOKEN + tokenData.getRefreshToken());

        //设置缓存
        String accessUuid = UUID.randomUUID().toString().replace("-","");
        String refreshUuid = UUID.randomUUID().toString().replace("-","R");
        redisOperate.set(RedisConstants.ACCESS_TOKE+accessUuid, value ,accessTime);
        redisOperate.set(RedisConstants.REFUSE_TOKEN+refreshUuid, value ,refreshTime);

        tokenData.setAccessToken(accessUuid);
        tokenData.setRefreshToken(refreshUuid);

        return tokenData;
    }

    @Override
    public boolean logout(TokenData tokenData) {
        //删除Redis用户缓存
        redisOperate.delete(RedisConstants.ACCESS_TOKE + tokenData.getAccessToken());
        redisOperate.delete(RedisConstants.REFUSE_TOKEN + tokenData.getRefreshToken());
        return true;
    }

    @Override
    public UserInfoEntity info() {
        Long userId = UserCacheManage.getUserIdCache();
        UserInfoEntity userInfoEntity = userRepository.findById(userId).orElse(new UserInfoEntity());
        userInfoEntity.setPassword("");
        return userInfoEntity;
    }

    @Override
    public boolean update(UserInfoEntity userInfo) {
        Long userId = UserCacheManage.getUserIdCache();
        Optional<UserInfoEntity> option = userRepository.findById(userId);
        if(option.isPresent()){
            UserInfoEntity entity = option.get();
            entity.setAvatar(userInfo.getAvatar());
            entity.setUserName(userInfo.getUserName());
            entity.setSex(userInfo.getSex());
            entity.setPhone(userInfo.getPhone());
            entity.setEmail(userInfo.getEmail());
            entity.setBirthday(userInfo.getBirthday());
            entity.setCity(userInfo.getCity());
            entity.setSign(userInfo.getSign());
            entity.setUpdateTime(new Date());
            userRepository.save(entity);
            return true;
        }else {
            return false;
        }
    }

}
